const std = @import("std");
const LockedFifo = @import("lockedfifo.zig").LockedFifo;

test "simple test" {
    try lockedfifo_main();
}

const lockedFifo = LockedFifo(i64, 10);

fn receiver(pipe: *lockedFifo, m: *std.Thread.Mutex) !void {
    var n: isize = 0;
    while (true) {
        const val = pipe.readItem() catch |err| {
            switch (err) {
                error.PipeClosed => std.debug.print("receiver: connection closed\n", .{}),
                error.OutOfMemory => std.debug.print("receiver: error\n", .{}),
            }
            return;
        };

        m.lock();
        std.debug.print("thread receive: {d}\n", .{val});
        m.unlock();

        std.Thread.sleep(100000000);
        n += 1;
        if (n == 15) {
            pipe.close();
        }
    }
}

fn lockedfifo_main() !void {
    var m = std.Thread.Mutex{};
    var p = lockedFifo{};

    defer p.deinit();

    const t = try std.Thread.spawn(.{}, receiver, .{ &p, &m });

    for (1..30) |i| {
        const v: i64 = @intCast(i);

        p.writeItem(v) catch |err| {
            switch (err) {
                error.PipeClosed => std.debug.print("main.writeItem: connection closed\n", .{}),
                error.OutOfMemory => std.debug.print("main.writeItem: error\n", .{}),
            }
            break;
        };

        m.lock();
        std.debug.print("main write: {d}\n", .{v});
        m.unlock();
    }
    std.Thread.sleep(500000000);
    std.debug.print("app time past, close\n", .{});
    p.close();
    t.join();
}
